package com.leyou.trade.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.auth.utils.UserContext;
import com.leyou.common.exception.LyException;
import com.leyou.item.client.ItemClient;
import com.leyou.item.dto.SkuDTO;
import com.leyou.trade.dto.OrderDTO;
import com.leyou.trade.entity.Order;
import com.leyou.trade.entity.OrderDetail;
import com.leyou.trade.entity.OrderLogistics;
import com.leyou.trade.mapper.OrderMapper;
import com.leyou.trade.service.CartService;
import com.leyou.trade.service.OrderDetailService;
import com.leyou.trade.service.OrderLogisticsService;
import com.leyou.trade.service.OrderService;
import com.leyou.user.client.UserClient;
import com.leyou.user.dto.AddressDTO;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.leyou.common.constants.MQConstants.ExchangeConstants.ORDER_EXCHANGE_NAME;
import static com.leyou.common.constants.MQConstants.RoutingKeyConstants.EVICT_ORDER_KEY;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    @Autowired
    private OrderLogisticsService logisticsService;

    @Autowired
    private OrderDetailService detailService;

    @Autowired
    private ItemClient itemClient;

    @Autowired
    private UserClient userClient;

    @Autowired
    private CartService cartService;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Override
    @GlobalTransactional
    public Long addOrder(OrderDTO orderVO) {
        Map<Long, Integer> cartsMap = orderVO.getCarts();
        if(CollectionUtils.isEmpty(cartsMap)){
            throw new LyException(401,"下单失败，请最少结算一件商品");
        }

        //减库存
        try {
            itemClient.reduceSkuStock(cartsMap);
        } catch (Exception e) {
            throw new LyException(401,"下单失败");
        }

        Order order = new Order();

        order.setPostFee(0L);
        order.setStatus(1);
        order.setUserId(UserContext.getUser().getId());
        order.setPaymentType(orderVO.getPaymentType());

        //查询订单中的所有商品
        List<SkuDTO> skuDTOS = itemClient.querySkuByIds(new ArrayList<>(cartsMap.keySet()));

        if(skuDTOS == null){
            throw new LyException(401,"下单失败，商品已过期");
        }

        Long totalFee = 0L;

        //计算总金额
        for (SkuDTO skuDTO : skuDTOS) {
            totalFee += skuDTO.getPrice() * cartsMap.get(skuDTO.getId());
        }

        order.setTotalFee(totalFee);
        order.setActualFee(totalFee);

        boolean success;

        //创建订单
        success = save(order);
        if(!success){
            throw new LyException(400,"创建订单失败");
        }

        List<OrderDetail> orderDetailList = skuDTOS.stream().map(skuDTO -> {
            OrderDetail orderDetail = new OrderDetail();

            orderDetail.setOrderId(order.getOrderId());
            orderDetail.setSkuId(skuDTO.getId());
            orderDetail.setNum(cartsMap.get(skuDTO.getId()));
            orderDetail.setTitle(skuDTO.getTitle());
            orderDetail.setSpec(skuDTO.getSpecialSpec());
            orderDetail.setPrice(skuDTO.getPrice());
            orderDetail.setImage(StringUtils.substringAfter(skuDTO.getImages(),","));

            return orderDetail;
        }).collect(Collectors.toList());

        //创建订单详情
        success = detailService.saveBatch(orderDetailList);
        if(!success){
            throw new LyException(400,"创建订单失败");
        }

        OrderLogistics orderLogistics = new OrderLogistics();

        //获取收货地址
        Long id = UserContext.getUser().getId();
        Long addressId = orderVO.getAddressId();
        AddressDTO address = userClient.findAddress(id, addressId);

        //存储收货地址
        orderLogistics.setOrderId(order.getOrderId());
        BeanUtils.copyProperties(address,orderLogistics);
        success = logisticsService.save(orderLogistics);
        if(!success){
            throw new LyException(400,"创建订单失败");
        }

//        //删除购物车对应商品
//        for (SkuDTO skuDTO : skuDTOS) {
//            cartService.deleteCart(skuDTO.getId());
//        }
        amqpTemplate.convertAndSend(ORDER_EXCHANGE_NAME, EVICT_ORDER_KEY, order.getOrderId());
        return order.getOrderId();
    }

    @Override
    public void closeOrder() {
        Date deadLine = DateTime.now().minusSeconds(30).toDate();

        List<Order> evictOrders = this.query().eq("status", 1).lt("create_time", deadLine).list();
//        List<Order> evictOrders = this.baseMapper.queryOrder(deadLine);
        if(CollectionUtils.isEmpty(evictOrders)){
            return;
        }

        List<OrderDetail> orderDetails = this.detailService.query()
                .in("order_id",
                        evictOrders.stream().map(Order::getOrderId).collect(Collectors.toList()))
                .list();

        Map<Long,Integer> cartsMap = new HashMap<>();

        orderDetails.forEach(orderDetail -> {
            Long orderId = orderDetail.getOrderId();
            Integer num = orderDetail.getNum();

            if(cartsMap.containsKey(orderId)){
                cartsMap.put(orderId,cartsMap.get(orderId)+num);
            }else{
                cartsMap.put(orderId,num);
            }
        });

        this.itemClient.plusSkuStock(cartsMap);

        evictOrders.forEach(evictOrder ->{
            evictOrder.setStatus(5);
            evictOrder.setCloseTime(new Date());
        });

        this.updateBatchById(evictOrders);

        /*update().set("status",5)
                .set("close_time",new Date())
                .eq("status",1)
                .lt("create_time",deadLine)
                .update();*/







        //       boolean s=baseMapper.updateByStatusAndTime(new Date(),deadLine);
    }

    @Override
    @GlobalTransactional
    public void evictOrderIfNecessary(Long orderId) {
        Order order = this.getById(orderId);

        if(1==order.getStatus()){
            List<OrderDetail> orderDetailList = this.detailService.query()
                    .eq("order_id", orderId).list();

            Map<Long,Integer> map = new HashMap<>();

            orderDetailList.forEach(orderDetail -> {
                Long skuId = orderDetail.getSkuId();
                Integer num = orderDetail.getNum();
                map.put(skuId,num);
            });

            this.itemClient.plusSkuStock(map);

            order.setStatus(5);
            order.setCloseTime(new Date());
            this.updateById(order);
        }
    }

}
